local VERSION = 1;
local lib = LibStub:NewLibrary("AddonConfig", VERSION);

-- already loaded and no upgrade necessary
if (not lib) then
  LibStub("AddonConfig").CheckLibraryHooks();
	return
end

--------------------------------------------------------------------------
-- from here on in, its the real thing
--------------------------------------------------------------------------

if (lib.PageTabs == nil) then lib.PageTabs = {} end
----------------------------------------------------------------------------
-- AddonConfig needs to hook into some of GameConfigFrames main functions
-- prepare those here
----------------------------------------------------------------------------

-- Workaround so that the hooks won't be stacked on the old versions
-- AddonConfigs replacements if theres simply a higher version available.
-- This has the disadvantage that any other addon that hooks those
-- functions and is loaded between the old and the new version of 
-- AddonConfig won't get its hooking function executed.
if (lib.Original == nil) then
	lib.Original = {
		GCF_OnApply = GCF_OnApply;
		GameConfig_OnRestoreAll = GameConfig_OnRestoreAll;
		GameConfigFrame_OnShow = GameConfigFrame_OnShow;
	}
end

lib.Replacement = {
	GCF_OnApply = function()
		-- out("AddonConfig: OnApply();");
		lib.Original.GCF_OnApply();

		if (table.getn(lib.PageTabs)) then
			for i, v in ipairs(lib.PageTabs) do
				v.fnApply();
			end
		end
	end,
	------------------------------------------------------------
	GameConfig_OnRestoreAll = function()
		-- out("AddonConfig: OnRestore();");
		lib.Original.GameConfig_OnRestoreAll();

		if (table.getn(lib.PageTabs)) then
			for i, v in ipairs(lib.PageTabs) do
				v.fnDefault();
			end
		end
	end,
	------------------------------------------------------------
	GameConfigFrame_OnShow = function(this)
		lib.Original.GameConfigFrame_OnShow(this);

		if (table.getn(lib.PageTabs)) then
			for i, v in ipairs(lib.PageTabs) do
				--out("PageTab: "..i.." -> "..tostring(v.name));
				v.fnReadSettings();
			end
		end
	end,
}

-- hook the real functions
GCF_OnApply             = lib.Replacement.GCF_OnApply;
GameConfig_OnRestoreAll = lib.Replacement.GameConfig_OnRestoreAll;
GameConfigFrame_OnShow  = lib.Replacement.GameConfigFrame_OnShow;

----------------------------------------------------------------------------
-- AddonConfig API to use for other Addons
----------------------------------------------------------------------------
-- this is the main function that other addons are supposed to call
lib.RegisterConfig = function(name, buttonTitle, configFrame, version, author, fnDefault, fnReadSettings, fnApply)
	local newTable = {
		name = name, 
		buttonTitle = buttonTitle,
		configFrame = configFrame,
		version = version,
		author = author,
		fnDefault = fnDefault,
		fnReadSettings = fnReadSettings,
		fnApply = fnApply,
	}
    
	lib.RegisterConfigTable(newTable)
end

lib.RegisterConfigTable = function(newTable)
  -- if we have no starting point yet, find one
	if (lib.TabStart == nil) then
		for i = 1, 20 do
			if (getglobal("GCF_Page"..i) == nil) then
				lib.TabStart = i;
				break
			end
		end
	end
  
  -- there is only space for exactly 29 buttons, some of those already in use
  if (table.getn(lib.PageTabs) == 29 - lib.TabStart) then
  	return
  end

  -- On ReloadUI() (and perhaps even on character change) this lib will remain
  -- the same, yet all regular addons will start registering again. So we 
  -- have to look if there is already an entry like that and if so, we simply 
  -- have to replace it.
  local oldKey = lib.CheckTableForAddonName(newTable.name);
  local pos;
	if (oldKey) then
		lib.PageTabs[oldKey] = newTable;
		pos = oldKey;
	else
    -- insert it
		table.insert(lib.PageTabs, newTable);
		pos = table.getn(lib.PageTabs);
	end

	GCF_PageTab[(lib.TabStart-1) + pos] = lib.PageTabs[pos].configFrame;
	local button = getglobal("GameConfigFramePagebut" .. ((lib.TabStart-1) + pos));
	if (lib.PageTabs[pos].buttonTitle and string.len(lib.PageTabs[pos].buttonTitle) > 0) then
		button:SetText(lib.PageTabs[pos].buttonTitle);
	else
		button:SetText("AddonConfig #"..pos);
	end
	button:SetID((lib.TabStart-1)+pos);
	button:ClearAllAnchors();
	button:SetAnchor("TOPLEFT", "BOTTOMLEFT", getglobal("GameConfigFramePagebut"..((lib.TabStart-1)+pos-1)), 0, 5);
	button:Show();
end

lib.CheckTableForAddonName = function(name)
	for key, val in ipairs(LibStub("AddonConfig").PageTabs) do
		if (val.name == name) then
			return key
		end
	end
end

-- Once a session this lib has to set some hooks. That means, it has to 
-- set them again if the player does a ReloadUI() or changes characters
-- without quitting the client.
lib.CheckLibraryHooks = function()
	-- On character change or reloadui, everything was already loaded once. 
	-- That means we can simply assume that there won't be a higher version
	-- of this lib to replace an old one. So we just check if the functions
	-- we want to hook match our own functions.

	-- they don't match, hook again
	if (GCF_OnApply ~= lib.Replacement.GCF_OnApply) then
	  -- save those functions somewhere else
		lib.Original = {
			GCF_OnApply = GCF_OnApply;
			GameConfig_OnRestoreAll = GameConfig_OnRestoreAll;
			GameConfigFrame_OnShow = GameConfigFrame_OnShow;
		}

		-- place the library functions there instead
		GCF_OnApply             = lib.Replacement.GCF_OnApply;
		GameConfig_OnRestoreAll = lib.Replacement.GameConfig_OnRestoreAll;
		GameConfigFrame_OnShow  = lib.Replacement.GameConfigFrame_OnShow;
	end
end











